@@ -57,17 +57,8 @@ class Service < ActiveRecord::Base |
||
57 | 57 |
(config = Devise.omniauth_configs[provider.to_sym]) && config.args[1] |
58 | 58 |
end |
59 | 59 |
|
60 |
- def self.provider_specific_options(omniauth) |
|
61 |
- case omniauth['provider'].to_sym |
|
62 |
- when :'37signals' |
|
63 |
- { user_id: omniauth['extra']['accounts'][0]['id'], name: omniauth['info']['name'] } |
|
64 |
- else |
|
65 |
- { name: omniauth['info']['nickname'] || omniauth['info']['name'] } |
|
66 |
- end |
|
67 |
- end |
|
68 |
- |
|
69 | 60 |
def self.initialize_or_update_via_omniauth(omniauth) |
70 |
- options = provider_specific_options(omniauth) |
|
61 |
+ options = get_options(omniauth) |
|
71 | 62 |
|
72 | 63 |
find_or_initialize_by(provider: omniauth['provider'], uid: omniauth['uid'].to_s).tap do |service| |
73 | 64 |
service.assign_attributes token: omniauth['credentials']['token'], |
@@ -78,4 +69,24 @@ class Service < ActiveRecord::Base |
||
78 | 69 |
options: options |
79 | 70 |
end |
80 | 71 |
end |
72 |
+ |
|
73 |
+ def self.register_options_provider(provider_name, &block) |
|
74 |
+ option_providers[provider_name] = block |
|
75 |
+ end |
|
76 |
+ |
|
77 |
+ def self.get_options(omniauth) |
|
78 |
+ option_providers.fetch(omniauth['provider'], option_providers['default']).call(omniauth) |
|
79 |
+ end |
|
80 |
+ |
|
81 |
+ private |
|
82 |
+ @@option_providers = HashWithIndifferentAccess.new |
|
83 |
+ cattr_reader :option_providers |
|
84 |
+ |
|
85 |
+ register_options_provider('default') do |omniauth| |
|
86 |
+ {name: omniauth['info']['nickname'] || omniauth['info']['name']} |
|
87 |
+ end |
|
88 |
+ |
|
89 |
+ register_options_provider('37signals') do |omniauth| |
|
90 |
+ {user_id: omniauth['extra']['accounts'][0]['id'], name: omniauth['info']['name']} |
|
91 |
+ end |
|
81 | 92 |
end |
@@ -5,22 +5,23 @@ describe OmniauthCallbacksController do |
||
5 | 5 |
sign_in users(:bob) |
6 | 6 |
OmniAuth.config.test_mode = true |
7 | 7 |
request.env["devise.mapping"] = Devise.mappings[:user] |
8 |
- request.env["omniauth.auth"] = JSON.parse(File.read(Rails.root.join('spec/data_fixtures/services/twitter.json'))) |
|
9 | 8 |
end |
10 | 9 |
|
11 | 10 |
describe "accepting a callback url" do |
12 | 11 |
it "should update the user's credentials" do |
12 |
+ request.env["omniauth.auth"] = JSON.parse(File.read(Rails.root.join('spec/data_fixtures/services/twitter.json'))) |
|
13 | 13 |
expect { |
14 | 14 |
get :twitter |
15 | 15 |
}.to change { users(:bob).services.count }.by(1) |
16 | 16 |
end |
17 |
+ end |
|
17 | 18 |
|
18 |
- # it "should work with an unknown provider (for now)" do |
|
19 |
- # request.env["omniauth.auth"]['provider'] = 'unknown' |
|
20 |
- # expect { |
|
21 |
- # get :unknown |
|
22 |
- # }.to change { users(:bob).services.count }.by(1) |
|
23 |
- # expect(users(:bob).services.first.provider).to eq('unknown') |
|
24 |
- # end |
|
19 |
+ describe "handling a provider with non-standard omniauth options" do |
|
20 |
+ it "should update the user's credentials" do |
|
21 |
+ request.env["omniauth.auth"] = JSON.parse(File.read(Rails.root.join('spec/data_fixtures/services/37signals.json'))) |
|
22 |
+ expect { |
|
23 |
+ get "37signals" |
|
24 |
+ }.to change { users(:bob).services.count }.by(1) |
|
25 |
+ end |
|
25 | 26 |
end |
26 | 27 |
end |
@@ -98,6 +98,7 @@ describe Service do |
||
98 | 98 |
expect(service.token).to eq('a1b2c3d4...') |
99 | 99 |
expect(service.secret).to eq('abcdef1234') |
100 | 100 |
end |
101 |
+ |
|
101 | 102 |
it "should work with 37signals services" do |
102 | 103 |
signals = JSON.parse(File.read(Rails.root.join('spec/data_fixtures/services/37signals.json'))) |
103 | 104 |
expect { |
@@ -113,6 +114,7 @@ describe Service do |
||
113 | 114 |
expect(service.options[:user_id]).to eq(12345) |
114 | 115 |
service.expires_at = Time.at(1401554352) |
115 | 116 |
end |
117 |
+ |
|
116 | 118 |
it "should work with github services" do |
117 | 119 |
signals = JSON.parse(File.read(Rails.root.join('spec/data_fixtures/services/github.json'))) |
118 | 120 |
expect { |
@@ -126,4 +128,27 @@ describe Service do |
||
126 | 128 |
expect(service.token).to eq('agithubtoken') |
127 | 129 |
end |
128 | 130 |
end |
131 |
+ |
|
132 |
+ describe 'omniauth options provider registry for non-conforming omniauth responses' do |
|
133 |
+ describe '.register_options_provider' do |
|
134 |
+ before do |
|
135 |
+ Service.register_options_provider('test-omniauth-provider') do |omniauth| |
|
136 |
+ { name: omniauth['special_field'] } |
|
137 |
+ end |
|
138 |
+ end |
|
139 |
+ |
|
140 |
+ after do |
|
141 |
+ Service.option_providers.delete('test-omniauth-provider') |
|
142 |
+ end |
|
143 |
+ |
|
144 |
+ it 'allows gem developers to add their own options provider to the registry' do |
|
145 |
+ actual_options = Service.get_options({ |
|
146 |
+ 'provider' => 'test-omniauth-provider', |
|
147 |
+ 'special_field' => 'A Great Name' |
|
148 |
+ }) |
|
149 |
+ |
|
150 |
+ expect(actual_options[:name]).to eq('A Great Name') |
|
151 |
+ end |
|
152 |
+ end |
|
153 |
+ end |
|
129 | 154 |
end |